<?php

/**
 * 行云供应商（中小B）模式
 * @author huj
 */
namespace App\Service\VendorClient\ShopXingYun;

use App\Service\BaseService;
use App\Service\Code\Normal;
use Service\AppService\IdService;
use App\Service\CodeService\UuidBuilderService;
use App\Service\TaskServer\TaskWorker;
use App\Model\PssModel\ServiceConfig;

class ShopXingYunXbV2ApiClient extends BaseService 
{
    protected $clientConfig;
    public function __construct($apiBody = []) {
        $this->clientConfig = $apiBody;
    }
    
    private $queryGoodsRoute=[
        'get_product_category_v2',
        'get_product_list_v2',
        'get_product_detail_v2'
    ];

    /**
     * 创建订单
     */
    public function createOrder(array $params = []) 
    {
        $orderInfo = $params['supplierOrder'];
        $orderItem = $params['orderGoods'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];

        //支付流水号
        $pay_sn = $order['paySerial'] ?? $orderInfo['pay_sn'];
        //运费
        $deliver_money = $orderInfo['deliver_money'];
        //优惠
        $discount_money = $orderInfo['discount_money'];
        //下单支付的时候支付信息
        $apply_extends = @json_decode($orderInfo['apply_extends'], true);
        //支付时间
        $pay_time = date('Y-m-d H:i:s', time());
        //支付流水号
        $pay_sn   = $orderInfo['pay_sn'];
        $order_sn = $orderInfo['supplier_dsn'];
        //订单优惠金额
        $real_total_money      = $orderInfo['real_total_money'];
        //组装商品数据列表
        $goodsList = [];
        $goodsMoneyOrigin = 0;
        foreach ($orderItem as $v) {
            $goodsMoneyOrigin = bcadd($goodsMoneyOrigin, bcmul($v['price'], $v['quantity'], 2), 2);
        }
        $hasDiscountMoney = $order_pay_amount = $channel_discount_amount = $goodsTotalMoney = 0;
        $goodsNum = count($orderItem);
        foreach ($orderItem as $key => $item) 
        {
            $price            = (string)$item['price'];
            $spec_num         = (string)$item['spec_num'];
            $quantity         = (string)$item['quantity'];
            $supplier_skucode = $item['supplier_skucode'];
            $goods_type       = $item['goods_type'];
            $buyNum           = $spec_num * $quantity;
            
            //分摊优惠金额到单个商品
            if($key == $goodsNum - 1)
            {
                $skuDiscountAmountTotal = bcsub((string)$discount_money,(string)$hasDiscountMoney,2);
            }
            else
            {
                $singleGoodsTotalPrice  = bcmul((string)$price,(string)$quantity,2);
                $scale                  = bcdiv((string)$singleGoodsTotalPrice,(string)$goodsMoneyOrigin,4);
                $skuDiscountAmountTotal = bcmul((string)$scale,(string)$discount_money,2);
                $hasDiscountMoney       = bcadd((string)$hasDiscountMoney,(string)$skuDiscountAmountTotal, 2);
            }
            
            //原始销售单价
            $singlePrice                = bcdiv((string)$price,(string)$spec_num, 3);
            $singlePrice                = ceil(bcmul((string)$singlePrice,'100',1));
            $singlePrice                = bcdiv((string)$singlePrice, '100',2);            
            //向上取整3位收上去的
            $singleNewTotalPrice        = bcmul((string)$singlePrice,(string)$buyNum,2);
            $signleOldTotalPrice        = bcmul((string)$price,(string)$quantity,2);
            $diff_price                 = bcsub((string)$singleNewTotalPrice,(string)$signleOldTotalPrice,2);
            //优惠金额还需要加上补差金额否则无法过去
            $skuDiscountAmountTotal     = bcadd((string)$diff_price,(string)$skuDiscountAmountTotal,2);
            //单个商品实际支付总金额
            $sku_tax_amount             = bcsub((string)$singleNewTotalPrice,(string)$skuDiscountAmountTotal,2);
            
            $goodsInfo = [
                'sku_id'                  => $supplier_skucode,//商品编码（sku_id）
                'package_num'             => 1,//包装规格【如无匹配包装规格可传0，生成订单的包装规格会按下单数量/包装规格，取最大能除尽的规格】
                'buy_num'                 => $buyNum,//购买数量
                'sku_price'               => (string)$singlePrice,//渠道售价(包装规格单价,如package_num = 2,此字段表示的是以包装规格为2件计算的单价，单位：元，保留两位小数)
                'sku_tax_amount'          => 0.00,//综合税费(单位：元，保留两位小数)
                'sku_discount_amount'     => 0.00,//平台优惠金额(单位：元，保留两位小数）
                'channel_discount_amount' => $skuDiscountAmountTotal, //渠道优惠金额(单位：元，保留两位小数）
                'sku_pay_amount'          => $sku_tax_amount,//终端支付金额(单位：元，保留两位小数)//1.01   161.01  1
                'price_type'              => $goods_type == 1 ? 1 : 2,//渠道价格类型（1含税，2不含税）【非保税默认为含税】
            ];
            
            ksort($goodsInfo);
            $goodsList[]     = $goodsInfo;
            $goodsTotalMoney = bcadd((string)$goodsTotalMoney, (string)$singleNewTotalPrice, 2);
            $channel_discount_amount = bcadd((string)$channel_discount_amount, (string)$skuDiscountAmountTotal, 2);
        }
        
        //订单总价（商品保税价格 + 运费） 暂时不这样计算
        $totalMoney         = bcadd((string)$goodsTotalMoney, (string)$deliver_money, 2);//分摊计算出来的订单总金额
        $order_pay_amount   = bcsub((string)$totalMoney,(string)$channel_discount_amount,2);//实际支付总金额
        if( bccomp($real_total_money, $order_pay_amount,2) != 0 ) {
            return Normal::returnCode(Normal::FAIL,"订单实际支付金额：{$real_total_money},汇总金额为：{$order_pay_amount}，核算不一致!");
        }
        
        //商品类型
        $goods_type         = current($orderItem)['goods_type'];
        
        //获取支付方式配置
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $pay_value      = ServiceConfig::instance()->getConfigByEventsValue('shopxyb2b', ServiceConfig::TYPE_PAY, $PayCompanyCode);
        if (empty($pay_value)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$PayCompanyCode}】未映射，请联系管理员处理");
        }

        $city       = $this->getCity($orderInfo['province']);
        $province   = $this->getProvince($orderInfo['province']);

        //创建订单数据
        $data              = [
            'opcode'                  => 'add_custom_order_v2',
            'biz_content'             => [
                'order_type'              => !empty($this->clientConfig['order_type']) ? $this->clientConfig['order_type'] : ($goods_type == 1 ? 1 : 2),
                'push_type'               => 1,//三单对碰推单方式（1.代推订单和运单，2.代推运单）【保税订单必填】
                'merchant_order_id'       => $order_sn,
                'pay_type'                => $this->clientConfig['pay_type'] ?? 1,//付款方式：（1.余额支付，2.信用支付）
                'buyer_name'              => $orderInfo['buyer_realname'],
                'buyer_card_id'           => $orderInfo['buyer_idcard'],
                'recipient_name'          => $orderInfo['receive_name'],
                'recipient_card_id'       => $orderInfo['buyer_idcard'],
                'recipient_mobile'        => $orderInfo['recveive_phone'],
                'order_province'          => $province,
                'order_city'              => $city ?? $orderInfo['city'],
                'order_area'              => $orderInfo['district'],
                'order_address'           => $orderInfo['receive_address'],
                'order_time'              => date("Y-m-d H:i:s", time()),
                'custom_pay_order'        => $order_sn,
                'pay_time'                => $pay_time,
                //支付方式：(1 支付宝,2 微信,3 商盟,4 汇付,5 通联,9 联动,10 云闪付,11 平安付,12 苏宁易付宝,13 银联,14 汇聚支付 15 新生支付 16 有赞支付 17易生支付 18合利宝 19盛付通 20宝付 21多多支付)【保税订单则为必填项】
                'third_pay_type'          => $pay_value,
                //支付公司编码 【保税订单则为必填项】
                'pay_custom_no'           => $order['payCommanyCode'] ?? $apply_extends['payCommanyCode'],
                //支付公司名称 【保税订单则为必填项】
                'pay_company_name'        => $order['payCommanyName'] ?? $apply_extends['payCommanyName'],
                //交易流水号 【保税订单则为必填项】
                'pay_third_no'            => $order['paySerial'] ?? $apply_extends['paySerial'],
                'sku_list'                => $goodsList,
                'order_pay_amount'        => $order_pay_amount,//1.00
                'order_discount_amount'   => '0.00',
                'channel_discount_amount' => $channel_discount_amount,//109.01
                'order_freight_amount'    => $deliver_money,//0.00
                //'remark'                    => $orderInfo['order_remark'],
                'order_total_amount'      => $totalMoney,//110.01
                'ecommerce_name'          => $order['enterpriseName'] ?? $apply_extends['enterpriseName'] ?? '',
                'ecommerce_code'          => $order['enterpriseNum'] ?? $apply_extends['enterpriseNum'] ?? '',
            ]
        ];
        return $this->execute($data);
    }



    private function getProvince($province)
    {
        if(in_array($province,['天津','北京','上海','重庆'])){
            return $province .'市'; 
        }
        return $province;
    }

    /**
     * 获取行云城市的方法
     * @param [type] $city
     * @return array
     */
    private function getCity($province){
        if(in_array($province,['天津','北京','上海','重庆'])){
            return $province .'市'; 
        }
        if(in_array($province,['天津市','北京市','上海市','重庆市'])){
            return $province;
        }
        return null;
    }

    /**
     * 取消订单
     */
    public function cancelOrder($params = []) {
        $data              = [
            'opcode'            => 'add_cancel_order_v2',
            'biz_content'       => [
                'merchant_order_id' => $params['supplierOrder']['supplier_dsn'],
                'cancel_reason'     => $params['order']['exceptReason'] ?? '不想要了'
            ]
        ];
        return $this->execute($data);
    }

    /**
     * 获取商品列表
     */
    public function queryGoodsList($params = []) {
        if (empty($params['category_id'])) {
            return Normal::returnCode(Normal::FAIL, "except param category_id");
        }
        $data              = [
            'opcode'      => 'get_product_list_v2',
            'biz_content' => [
                'size'        => $params['limit'] ?? 20,
                'current'     => $params['page'] ?? 1,
                'category_id' => $params['category_id'],
            ]
        ];
        //判断是否有指定类型
        if (!empty($this->clientConfig['trade_type'])){
            $data['biz_content']['trade_type'] = $this->clientConfig['trade_type'];
        }
        $response          = $this->execute($data);

        $responseData=[];
        foreach ($response['data']['sku_detail']['records'] as $item){
            if (isset($item['freight_list'])){
                unset($item['freight_list']);
            }
            $responseData[]=$item;
        }

        $result = ['total' => $response['data']['sku_detail']['total'], 'data' => $responseData ,'has_next'=>$response['data']['sku_detail']['hasNext']];
        return Normal::returnCode(Normal::SUC, '获取成功', $result);
    }

    /**
     * 获取商品列表
     */
    public function queryGoodsDetail($params = []) {
        $sku_id = $params['sku_id'];
        //拿到所有SKU
        $data              = [
            'opcode'      => 'get_product_detail_v2',
            'biz_content' => ['sku_id_list'=>[$sku_id]]
        ];
        $data['sign']      = $this->getSign($data);
        $data['sign_type'] = $this->clientConfig['sign_type'];
        $response          = $this->execute($data);
        $result = ['total' => 1, 'data' => $response['data']['list']];
        return Normal::returnCode(Normal::SUC, '获取成功', $result);
    }

    
    /**
     * 查询商品分类 行云只要这个几个分类
     * 宠物用品：2000000001、
     * 母婴用品：2000000003、
     * 食品酒饮：2000000009、
     * 营养保健：2000000011、
     * 美容和个人护理：2000000002、
     * 钟表饰品：2000000014
     * @return array
     */
    public function queryGoodsCategory() {
        $data              = [
            'opcode'        => 'get_product_category_v2',
            'biz_content'   => [
                'parent_cat_id' => 0,
            ]
        ];
        $res =  $this->execute($data);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        if( empty($res['data']['category_list']) ) {
            return Normal::returnCode(Normal::FAIL,"当前行云分类获取异常");
        }
        if(!isset($this->clientConfig['category']) || empty($this->clientConfig['category'])){
            return $res;
        }
        $targetCategoryIds = explode('|', $this->clientConfig['category']);
        if(!$targetCategoryIds){
            return $res;
        }
        $originCategory = $res['data']['category_list'];
        foreach ($originCategory as $key => $v) {
            if(!in_array($v['category_id'], $targetCategoryIds)){
                unset($originCategory[$key]);
            }
        }
        if( empty($originCategory) ) {
            return Normal::returnCode(Normal::FAIL,"筛选后的分类数据异常");
        }
        $res['data']['category_list'] = array_values($originCategory);
        return $res;
    }
    
    /**
     * 获取sign参数
     */
    private function getSign($param = []) {
        ksort($param);
        $arr = [];
        foreach ($param as $k => $v) {
            if (is_array($v)) {
                $v = $this->getStr($v);
            }
            $arr[] = "{$k}={$v}";
        }
        $str = implode("&", $arr);
        $str = $str . $this->clientConfig['appSecret'];
        return md5($str);
    }

    public function getStr($v) {
        $sku_list = [];
        foreach ($v as $item) {
            $str = [];
            foreach ($item as $key => $v) {
                $str[] = "$key:$v";
            }
            $str        = implode(",", $str);
            $sku_list[] = "{$str}";
        }

        return "[{" . (implode("},{", $sku_list)) . "}]";
    }

    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute($param = []) {
        $data = [
            'opcode'      => $param['opcode'],
            'biz_content' => json_encode($param['biz_content']),
            'version'     => '2',
            'business_id' => UuidBuilderService::instance()->getCode(),
            'merchant_id' => $this->clientConfig['merchant_id']
        ];
        $data['sign']      = $this->getSign($data);
        $data['sign_type'] = $this->clientConfig['sign_type'];
        $url       = $this->clientConfig['baseurl'];
        $parameter = [
            [
                'tag'    => 'shopxyxb_' . $param['opcode'],
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $url,
                'data'   => $data,
                'method' => 'post',
                'format' => 'json',
                'header' => [],
                //'is_not_log' => 'yes'//不记日志
            ],
        ];
        if (in_array($data['opcode'], $this->queryGoodsRoute)) {
            $resTask = TaskWorker::instance()->addTask($parameter, 'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask  = current($resTask);
        $resHttp  = @json_decode($resTask['response']['result'], true);
        $errorMsg = $resHttp['ret_msg'] ?? '请求失败';
        if (isset($resHttp['ret_code']) && $resHttp['ret_code'] == Normal::SUC) {
            $data = @json_decode($resHttp['result_content'],true);
            return Normal::returnCode(Normal::SUC, "操作成功", $data);
        }
        return Normal::returnCode($resHttp['ret_code'] ?? 0, $errorMsg);
    }
}
